fix(agent_execution): resolve ActiveTask 'destroyed but pending' warning during teardown#1122
fix(agent_execution): resolve ActiveTask 'destroyed but pending' warning during teardown#1122arunmm8335 wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the _run_consumer method in active_task.py to await the _producer_task if it is not yet completed during shutdown. The review feedback correctly identifies that asyncio.CancelledError inherits from BaseException rather than Exception in Python 3.8+, meaning a cancellation error would propagate and bypass critical cleanup steps like decrementing the reference count. A code suggestion is provided to explicitly catch and handle asyncio.CancelledError.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| try: | ||
| await self._producer_task | ||
| except Exception as e: | ||
| logger.debug('Consumer[%s]: Awaited producer_task raised %r', self._task_id, e) |
There was a problem hiding this comment.
In Python 3.8+, asyncio.CancelledError inherits from BaseException rather than Exception. Since _producer_task is cancelled during task cancellation (e.g., via self._producer_task.cancel()), awaiting it here will raise asyncio.CancelledError.
Because the except Exception block does not catch BaseException, this error will propagate out of the finally block, preventing the remaining cleanup code (decrementing _reference_count and calling _maybe_cleanup()) from executing. This can lead to resource leaks and tasks not being properly cleaned up.
To fix this, explicitly catch asyncio.CancelledError and handle or ignore it.
| try: | |
| await self._producer_task | |
| except Exception as e: | |
| logger.debug('Consumer[%s]: Awaited producer_task raised %r', self._task_id, e) | |
| try: | |
| await self._producer_task | |
| except asyncio.CancelledError: | |
| pass | |
| except Exception as e: | |
| logger.debug('Consumer[%s]: Awaited producer_task raised %r', self._task_id, e) |
🧪 Code Coverage (vs
|
| Base | PR | Delta | |
|---|---|---|---|
| src/a2a/server/agent_execution/active_task.py | 95.92% | 95.48% | 🔴 -0.45% |
| Total | 92.99% | 92.97% | 🔴 -0.02% |
Generated by coverage-comment.yml
…ing during teardown
7b9e59a to
af85738
Compare
Fixes #1121. This PR resolves the issue where
ActiveTaskwould throw an asyncio warning when being garbage collected, by ensuring the_producer_taskis properly awaited during the_run_consumerteardown path, allowing queues to properly close without leaving dangling pending background tasks.